package com.datagateway.component;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 系统监控组件
 * 负责监控系统资源使用情况和性能指标
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class SystemMonitor {

    private static final Logger logger = LoggerFactory.getLogger(SystemMonitor.class);

    @Autowired
    private AlertManager alertManager;

    /**
     * 系统性能指标
     */
    private final AtomicLong totalProcessedMessages = new AtomicLong(0);
    private final AtomicLong totalFailedMessages = new AtomicLong(0);
    private final AtomicLong totalRetryCount = new AtomicLong(0);
    private final AtomicLong totalDeadLetterCount = new AtomicLong(0);
    private final AtomicLong totalRouteEvents = new AtomicLong(0);

    /**
     * 性能监控 - 每30秒执行一次
     */
    @Scheduled(fixedDelay = 30000)
    public void monitorSystemPerformance() {
        try {
            // 监控内存使用情况
            monitorMemoryUsage();
            
            // 监控处理性能
            monitorProcessingPerformance();
            
            // 监控队列状态
            monitorQueueStatus();
            
        } catch (Exception e) {
            logger.error("系统监控异常", e);
            alertManager.sendSystemErrorAlert("系统监控异常", e.getMessage());
        }
    }

    /**
     * 监控内存使用情况
     */
    private void monitorMemoryUsage() {
        try {
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            MemoryUsage heapMemory = memoryBean.getHeapMemoryUsage();
            
            long usedMemory = heapMemory.getUsed();
            long maxMemory = heapMemory.getMax();
            double usagePercent = (double) usedMemory / maxMemory * 100;
            
            // 记录内存使用情况
            logger.debug("内存使用情况: 已使用={} MB, 最大={} MB, 使用率={:.2f}%", 
                        usedMemory / 1024 / 1024, maxMemory / 1024 / 1024, usagePercent);
            
            // 发送内存告警
            alertManager.sendMemoryUsageAlert(usedMemory, maxMemory, usagePercent);
            
        } catch (Exception e) {
            logger.error("监控内存使用情况失败", e);
        }
    }

    /**
     * 监控处理性能
     */
    private void monitorProcessingPerformance() {
        try {
            long processed = totalProcessedMessages.get();
            long failed = totalFailedMessages.get();
            long total = processed + failed;
            
            if (total > 0) {
                double successRate = (double) processed / total * 100;
                double failureRate = (double) failed / total * 100;
                
                logger.debug("处理性能统计: 总数={}, 成功={}, 失败={}, 成功率={:.2f}%, 失败率={:.2f}%", 
                           total, processed, failed, successRate, failureRate);
                
                // 如果失败率过高，发送告警
                if (failureRate > 10) {
                    alertManager.sendPerformanceAlert("数据处理失败率", failureRate, 10.0);
                }
            }
            
        } catch (Exception e) {
            logger.error("监控处理性能失败", e);
        }
    }

    /**
     * 监控队列状态
     */
    private void monitorQueueStatus() {
        try {
            long retryCount = totalRetryCount.get();
            long deadLetterCount = totalDeadLetterCount.get();
            
            logger.debug("队列状态: 重试次数={}, 死信数量={}", retryCount, deadLetterCount);
            
            // 发送重试队列告警
            alertManager.sendRetryQueueAlert(retryCount, deadLetterCount);
            
        } catch (Exception e) {
            logger.error("监控队列状态失败", e);
        }
    }

    /**
     * 记录处理的消息
     * 
     * @param success 是否成功
     */
    public void recordProcessedMessage(boolean success) {
        if (success) {
            totalProcessedMessages.incrementAndGet();
        } else {
            totalFailedMessages.incrementAndGet();
        }
    }

    /**
     * 记录重试次数
     * 
     * @param count 重试次数
     */
    public void recordRetryCount(long count) {
        totalRetryCount.addAndGet(count);
    }

    /**
     * 记录死信数量
     * 
     * @param count 死信数量
     */
    public void recordDeadLetterCount(long count) {
        totalDeadLetterCount.addAndGet(count);
    }

    /**
     * 记录路由事件
     * 
     * @param dataSourceType 数据源类型
     * @param identifier 标识符
     * @param targetId 目标ID
     */
    public void recordRouteEvent(String dataSourceType, String identifier, String targetId) {
        totalRouteEvents.incrementAndGet();
        logger.debug("记录路由事件: {} -> {} -> {}", dataSourceType, identifier, targetId);
    }

    /**
     * 获取系统性能统计
     * 
     * @return 系统性能统计信息
     */
    public SystemPerformanceStatistics getSystemPerformanceStatistics() {
        long processed = totalProcessedMessages.get();
        long failed = totalFailedMessages.get();
        long total = processed + failed;
        
        return new SystemPerformanceStatistics(
            total,
            processed,
            failed,
            totalRetryCount.get(),
            totalDeadLetterCount.get(),
            totalRouteEvents.get(),
            total > 0 ? (double) processed / total * 100 : 0,
            total > 0 ? (double) failed / total * 100 : 0
        );
    }

    /**
     * 获取内存使用情况
     * 
     * @return 内存使用情况
     */
    public MemoryUsageInfo getMemoryUsageInfo() {
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapMemory = memoryBean.getHeapMemoryUsage();
        
        long usedMemory = heapMemory.getUsed();
        long maxMemory = heapMemory.getMax();
        double usagePercent = (double) usedMemory / maxMemory * 100;
        
        return new MemoryUsageInfo(
            usedMemory,
            maxMemory,
            usagePercent
        );
    }

    /**
     * 系统性能统计信息类
     */
    public static class SystemPerformanceStatistics {
        private final long totalMessages;
        private final long processedMessages;
        private final long failedMessages;
        private final long retryCount;
        private final long deadLetterCount;
        private final long routeEvents;
        private final double successRate;
        private final double failureRate;

        public SystemPerformanceStatistics(long totalMessages, long processedMessages, long failedMessages,
                                         long retryCount, long deadLetterCount, long routeEvents, double successRate, double failureRate) {
            this.totalMessages = totalMessages;
            this.processedMessages = processedMessages;
            this.failedMessages = failedMessages;
            this.retryCount = retryCount;
            this.deadLetterCount = deadLetterCount;
            this.routeEvents = routeEvents;
            this.successRate = successRate;
            this.failureRate = failureRate;
        }

        // Getter方法
        public long getTotalMessages() { return totalMessages; }
        public long getProcessedMessages() { return processedMessages; }
        public long getFailedMessages() { return failedMessages; }
        public long getRetryCount() { return retryCount; }
        public long getDeadLetterCount() { return deadLetterCount; }
        public long getRouteEvents() { return routeEvents; }
        public double getSuccessRate() { return successRate; }
        public double getFailureRate() { return failureRate; }

        @Override
        public String toString() {
            return String.format("SystemPerformanceStatistics{totalMessages=%d, processedMessages=%d, " +
                               "failedMessages=%d, retryCount=%d, deadLetterCount=%d, routeEvents=%d, " +
                               "successRate=%.2f%%, failureRate=%.2f%%}",
                               totalMessages, processedMessages, failedMessages, retryCount, 
                               deadLetterCount, routeEvents, successRate, failureRate);
        }
    }

    /**
     * 内存使用情况类
     */
    public static class MemoryUsageInfo {
        private final long usedMemory;
        private final long maxMemory;
        private final double usagePercent;

        public MemoryUsageInfo(long usedMemory, long maxMemory, double usagePercent) {
            this.usedMemory = usedMemory;
            this.maxMemory = maxMemory;
            this.usagePercent = usagePercent;
        }

        // Getter方法
        public long getUsedMemory() { return usedMemory; }
        public long getMaxMemory() { return maxMemory; }
        public double getUsagePercent() { return usagePercent; }
        public long getUsedMemoryMB() { return usedMemory / 1024 / 1024; }
        public long getMaxMemoryMB() { return maxMemory / 1024 / 1024; }

        @Override
        public String toString() {
            return String.format("MemoryUsageInfo{usedMemory=%d MB, maxMemory=%d MB, usagePercent=%.2f%%}",
                               getUsedMemoryMB(), getMaxMemoryMB(), usagePercent);
        }
    }
}
